/* 大致文档：
var paint = new Sketch({
	id: 'container', //此项必填  只需要是个div就可以了
	user: 'test', //当前用户
	canDraw: true, // 此项必填  能否画画
	sendMsg: function(msg) {
		console.log(msg);
	}, //要和其他端同步的数据 选填 默认为打印到控制台
	reportMsg: function(msg) {
		console.log(msg);
	}, //要传到服务器的数据  选填 默认为打印到控制台
	switchBoard: function(boardId) {
		console.log(boardId);
	}, //切换白板的回调  参数为 当前的白板id
	deleteBoard: function(boardId) {
		console.log(boardId);
	}, //删除白板的回调  参数为 被删除的白板id
	color: 4278190335, //画笔的颜色 rgba格式的数字(目前支持透明度为1)  选填 默认为 4278190335
	thin: 100, //画笔的粗细 万分数的宽度 选填 默认为 100
	backgroundColor: '#ffffff', //背景色 rgb格式 选填 默认为'#ffffff'
	type: 'line', //初始的画笔类型 选填 默认为 line  画笔类型包括:  line:随便画线  eraser: 橡皮擦  raser: 激光笔  pointselect: 点选  select: 选择框  move: 拖拽  graph-line:直线  graph-circle:圆   graph-rect:矩形  graph-circle-solid:实心圆(ios端暂未支持)
	graph-rect-solid: 实心矩形(ios端暂未支持)
	transparent: false, //在无背景图的时候背景是否透明 选填 默认为 true
	radius: 100 //万分数的宽度 选填 默认为 100,
});

paint.setColor(4278190335); //修改画笔颜色
paint.setThin(100); //修改画笔粗细
paint.setRadius(100); //修改橡皮擦粗细
paint.clear(); //清空当前白板
paint.revert(); //回退  回退前需要先调用 paint.canRevert();
paint.process(); //前进一步   前进前需要先调用 paint.canProcess();
paint.canRevert(); //能否回退 true:能
paint.canProcess(); //能否前进 true:能

paint.setBackgroundPic(url); //添加背景图
paint.cancelBackgroundPic(); //删除背景图

paint.getCurrentBoard(); //获取当前白板id
paint.switchBoard(boardId); //切换到白板 如果不存在 则会默认创建
paint.getBoardList(); //获取白板列表
paint.deleteBoard(boardId); //删除白板

paint.addData(data); //添加数据 data格式参考SDK数据协议
paint.addHistory(data); //添加历史数据  data为服务器数据的数组
*/

var Sketch = function(options) {
	if (!(this instanceof Sketch)) {
		return new Sketch(options);
	}
	this.option = shallowClone(options); //Object.assign({}, options);
	this.container = document.getElementById(this.option.id);
	this.width = this.container.clientWidth;
	this.height = this.container.clientHeight;

	// 发送数据
	this.sendMsg = this.option.sendMsg || function(data) {
		console.log(data);
	};
	// 上报数据
	this.reportMsg = this.option.reportMsg || function(data) {
		console.log(data);
	};
	// 切换白板
	this.infoSwitchBoard = this.option.infoSwitchBoard || function(data) {
		console.log(data);
	};
	// 当前画画的人
	this.user = options.user || 'test';
	// 要发送的内容
	this.sendData = [];
	// data：所有的对象  按照开始时间 排序
	this.data = {};
	// 操作data
	this.opData = {};
	this.opIndex = {};
	// userData 所有的用户的对象， 具体的对象和data里面是同一个
	this.userData = {};
	// 背景图
	this.backgroundPic = {};
	this.currentBoard = '#DEFAULT';
	this.boardList = ['#DEFAULT'];
	this.infoSwitchBoard({current: '#DEFAULT', list: this.boardList});
	this.data[this.currentBoard] = [];
	this.userData[this.currentBoard] = {};
	this.opData[this.currentBoard] = [];
	this.opIndex[this.currentBoard] = 0;
	this.backgroundPic[this.currentBoard] = {
		url: '',
		user: '',
		show: true
	}
	// 画画的选项
	this.color = this.dealColor(options.color || 4278190335);
	// this.thin = (options.thin || 100) / 10000 * this.height;
	this.thin = options.thin || 100;
	this.radius = options.radius || 100;
	this.backgroundColor = options.backgroundColor || '#ffffff';
	// 是否需要重绘
	this.needDraw = false;
	// 当前的状态   line:随便画线  eraser: 橡皮擦  raser: 激光笔  pointselect: 点选  select: 选择框  move: 拖拽  graph-line:直线
	// graph-circle:圆   graph-rect:矩形
	this.type = options.type || 'line';
	// 无背景图的时候  是否透明
	this.transparent = options.transparent || true;
	// 当前操作的seq
	this.seq = 0;
	// 当前被选择的元素列表
	this.selectedList = [];
	// 选择之后 拖拽时展示的总区域   点选为当前元素的外区域  框选为所有被选中的图形的总区域
	this.selectArea = {
		x: 0,
		y: 0,
		width: 0,
		height: 0
	}
	// 是否正在拖动  这个时候 多个selected元素需要展示最外层的框框
	this.isMoving = false;
	// 用于计算seq
	this.gSeq = 0;

	this.canDraw = options.canDraw;

	// 初始化userData
	if (!this.userData[this.currentBoard][this.user]) {
		this.userData[this.currentBoard][this.user] = [];
	}
	this.init();
}

Sketch.prototype.resize = function() {
	this.width = this.container.clientWidth;
	this.height = this.container.clientHeight;
}

Sketch.prototype.getEventLocation = function(event) {
	var result = {
		x: 0,
		y: 0
	}
	if (event.offsetX){
		result.x = event.offsetX;
		result.y = event.offsetY;
	} else {
		// 外层元素位置会变
		result.x = event.pageX - this.container.offsetLeft;
		result.y = event.pageY - this.container.offsetTop;
	}
	console.log(event.pageX, event.pageY);
	// 要转一下x y
	result.x = parseInt(result.x / this.width * 10000);
	result.y = parseInt(result.y / this.height * 10000);
	return result;
}

// 获取seq
Sketch.prototype.getSeq = function() {
	var time = parseInt(+ new Date() / 1000, 10);
	return time * Math.pow(2, 15) + (this.gSeq++);
}

// 全局重绘
Sketch.prototype.draw = function() {
	var self = this;
	var ctx = self.el.getContext("2d");
	// 先清空画板
	ctx.clearRect(0, 0, self.width, self.height);
	// 填充画板
	// 目前认为画板是透明的 暂时不添加背景色
	if (self.backgroundPic[self.currentBoard].url && self.backgroundPic[self.currentBoard].show) {
		self.img.src = self.backgroundPic[self.currentBoard].url;
		self.img.style.display = 'block';
	} else if (!self.option.transparent) {
		ctx.fillStyle = self.backgroundColor;
		ctx.fillRect(0, 0, self.width, self.height);
	}
	drawData();
	function drawEllipse(context, x, y, a, b, fill, color){
		context.save();
		var r = (a > b) ? a : b;
		var ratioX = a / r;
		var ratioY = b / r;
		context.scale(ratioX, ratioY);
		context.beginPath();
		context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false);
		context.closePath();
		context.restore();
		if(fill){
			context.fillStyle = color;
			context.fill();
		}
	}
	function drawData() {
		self.data[self.currentBoard].forEach(function(item) {
			if (item.type == 'line' && item.show) { // 画线
				// 先初始化
				var oldx = item.lines[0].x / 10000 * self.width;
				var oldy = item.lines[0].y / 10000 * self.height;

				item.lines.forEach(function(lineItem) {
					// 按照上次的位置和这次的位置画线
					ctx.beginPath();
					ctx.moveTo(oldx, oldy);
					ctx.lineTo(lineItem.x / 10000 * self.width, lineItem.y / 10000 * self.height);
					ctx.strokeStyle = item.color;
					ctx.lineWidth = item.thin / 10000 * self.height;
					ctx.lineCap = "round";
					ctx.stroke();
					// 更新参数
					oldx = lineItem.x / 10000 * self.width;
					oldy = lineItem.y / 10000 * self.height;
				});
			} else if (item.type == 'raser' && item.status) { // 画激光笔
				ctx.beginPath();
				ctx.arc(item.location.x / 10000 * self.width, item.location.y / 10000 * self.height, item.radius / 10000 * self.height, 0, Math.PI * 2);
				ctx.fillStyle = item.color;
				ctx.fill();
				ctx.closePath();
			} else if (item.type == 'select' && item.show) { // 画选框
				ctx.setLineDash([15, 5]);
				ctx.lineWidth = 1;
				ctx.strokeRect(item.startInfo.x / 10000 * self.width, item.startInfo.y / 10000 * self.height, (item.location.x - item.startInfo.x) / 10000 * self.width, (item.location.y - item.startInfo.y) / 10000 * self.height);
				ctx.setLineDash([]);
			} else if (item.type == 'graph' && item.show) { // 画图形
				if (item.graph == 'line') { // 画直线
					ctx.beginPath();
					ctx.moveTo(item.startPoint.x / 10000 * self.width, item.startPoint.y / 10000 * self.height);
					ctx.lineTo(item.endPoint.x / 10000 * self.width, item.endPoint.y / 10000 * self.height);
					ctx.strokeStyle = item.color;
					ctx.lineWidth = item.thin / 10000 * self.height;
					ctx.lineCap = "round";
					ctx.stroke();
				} else if (item.graph == 'rect') { // 画矩形
					// 先确定左上角
					var x = item.startPoint.x > item.endPoint.x
						? item.endPoint.x
						: item.startPoint.x;
					var y = item.startPoint.y > item.endPoint.y
						? item.endPoint.y
						: item.startPoint.y;
					ctx.strokeStyle = item.color;
					ctx.lineWidth = item.thin / 10000 * self.height;
					console.log('huajuxing');
					if (item.solid) { // 实心
						console.log('实心');
						ctx.fillStyle = item.color;
						ctx.fillRect(x / 10000 * self.width, y / 10000 * self.height, Math.abs(item.startPoint.x - item.endPoint.x) / 10000 * self.width, Math.abs(item.startPoint.y - item.endPoint.y) / 10000 * self.height);
					} else {
						console.log('空心');
						ctx.strokeRect(x / 10000 * self.width, y / 10000 * self.height, Math.abs(item.startPoint.x - item.endPoint.x) / 10000 * self.width, Math.abs(item.startPoint.y - item.endPoint.y) / 10000 * self.height);
					}
				} else if (item.graph == 'circle' || item.graph == 'oval') { // 画圆形或者椭圆
					var x = (item.startPoint.x + item.endPoint.x) / 2 / 10000 * self.width;
					var y = (item.startPoint.y + item.endPoint.y) / 2 / 10000 * self.height;
					var a = Math.abs(item.startPoint.x - item.endPoint.x) / 2 / 10000 * self.width;
					var b = Math.abs(item.startPoint.y - item.endPoint.y) / 2 / 10000 * self.height;
					ctx.strokeStyle = item.color;
					ctx.lineWidth = item.thin / 10000 * self.height;
					drawEllipse(ctx, x, y, a, b, item.solid, item.color);
					ctx.stroke();
				}
			}
		})
		if (self.isMoving) {
			ctx.setLineDash([15, 5]);
			ctx.lineWidth = 1;
			ctx.strokeRect((self.selectArea.x - self.thin) / 10000 * self.width, (self.selectArea.y - self.thin) / 10000 * self.height, (self.selectArea.width + self.thin * 2) / 10000 * self.width, (self.selectArea.height + self.thin * 2) / 10000 * self.height);
			ctx.setLineDash([]);
		} else {
			self.selectedList.forEach(function(item) {
				if (item.type == 'line') {
					ctx.setLineDash([15, 5]);
					ctx.lineWidth = 1;
					ctx.strokeRect((item.border.minX - item.thin * 2) / 10000 * self.width, (item.border.minY - item.thin * 2) / 10000 * self.height, (item.border.maxX - item.border.minX + item.thin * 4) / 10000 * self.width, (item.border.maxY - item.border.minY + item.thin * 4) / 10000 * self.height);
					ctx.setLineDash([]);
				} else if (item.type == 'graph') {
					var graphLargeX = item.endPoint.x;
					var graphLargeY = item.endPoint.y;
					var graphSmallX = item.startPoint.x;
					var graphSmallY = item.startPoint.y;
					ctx.setLineDash([15, 5]);
					ctx.lineWidth = 1;
					ctx.strokeRect((graphSmallX - item.thin * 2) / 10000 * self.width, (graphSmallY - item.thin * 2) / 10000 * self.height, (graphLargeX - graphSmallX + item.thin * 4) / 10000 * self.width, (graphLargeY - graphSmallY + item.thin * 4) / 10000 * self.height);
					ctx.setLineDash([]);
				}
			})
		}
	}
}

// 设置颜色 转为rgb
Sketch.prototype.dealColor = function(color) {
	var temp = parseInt(color).toString(16);
	temp = temp.substr(0, temp.length - 2);
	temp = '000000' + temp;
	temp = temp.substring(temp.length - 6, temp.length);
	return this.tools.hexToRgba(temp);
}

// 设置颜色 rgb转为数字
Sketch.prototype.formatColor = function(color) {
	var temp = this.tools.rgbaToHex(color);
	return parseInt(temp + 'ff', 16);
}

Sketch.prototype.tools = {
	hexToRgba: function(hex) {
		var rgb = [];
		hex.replace(/../g, function(color) {
			rgb.push(parseInt(color, 0x10)); //按16进制将字符串转换为数字
		});
		return "rgba(" + rgb.join(",") + ",1)";
	},
	rgbaToHex: function(rgba) {
		var color = rgba.toString().match(/\d+/g);
		var hex = '';
		for (var i = 0; i < 3; i++) {
			hex += ("0" + Number(color[i]).toString(16)).slice(-2);
		}
		return hex;
	}
}

// 处理历史消息 和普通的不一样
Sketch.prototype.addHistory = function(data) {
	var self = this;
	console.log(data);
	data.forEach(function(action) {
		action.content = JSON.parse(action.content);
		var boardId = action.content.boardId;
		var user = action.content.uid;
		if (!self.userData[boardId]) {
			self.initBoard(boardId);
		}
		if (!self.userData[boardId][user]) {
			self.userData[boardId][user] = [];
		}
		action.content.colorRGBA && (action.content.color = self.dealColor(action.content.colorRGBA));
		action.content.width && (action.content.thin = action.content.width);
		if (action.type == 'addLine') {
			var line;
			for (var i = 0; i < action.content.points.length - 1; i++) {
				var x = action.content.points[i].x;
				var y = action.content.points[i].y;
				if (i == 0) {
					line = new Line(user, {
						color: action.content.color,
						thin: action.content.thin,
						x: x,
						y: y,
						seq: action.content.points[i].seq,
						show: action.content.hidden
							? false
							: true
					});
				} else {
					line.lines.push({x: x, y: y, seq: action.content.points[i].seq});
					if (i == action.content.points.length - 1) {
						line.endSeq = action.content.points[i].seq;
					}
				}
				line.setBorder(x, y);
			}
			self.userData[boardId][user].push(line);
			self.data[boardId].push(line);
		} else if (action.type == 'displayLine') {
			var lines = action.content.lines;
			lines.forEach(function(line) {
				for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
					var item = self.userData[self.currentBoard][user][i];
					if (item.type == 'line' && item.startSeq == line.seq) {
						item.show = action.content.display
							? true
							: false;
					} else if (item.type == 'graph' && item.startPoint.seq == line.seq) {
						item.show = action.content.display
							? true
							: false;
					}
				}
			})
		} else if (action.type == 'addPatternLine' || action.type == 'addPatternCircle' || action.type == 'addPatternRectangle') {
			var list = {
				'addPatternLine': 'line',
				'addPatternCircle': 'oval',
				'addPatternRectangle': 'rect'
			};
			action.content.graph = list[action.type];
			action.content.beginPoint.x = action.content.beginPoint.x;
			action.content.endPoint.x = action.content.endPoint.x;
			action.content.beginPoint.y = action.content.beginPoint.y;
			action.content.endPoint.y = action.content.endPoint.y;
			action.content.seq = action.content.beginPoint.seq;
			action.content.show = action.content.hidden
				? false
				: true;
			action.content.solid = action.content.fillRect
				? true
				: false;
			var graph = new Graph(user, action.content);
			self.userData[boardId][user].push(graph);
			self.data[boardId].push(graph);
		} else if (action.type == 'image') {
			if (action.content.url) {
				self.setBackgroundPic(action.content.url);
			} else {
				self.cancelBackgroundPic();
			}
		} else if (action.type == 'clean') {
			self.clear();
		} else if (action.type == 'switchBoard') {
			if (!self.data[boardId]) {
				self.initBoard(boardId);
			}
			self.currentBoard = boardId;
			self.infoSwitchBoard({current: boardId, list: self.boardList});
		}
	});
	self.needDraw = true;
}

// 设置内容data
Sketch.prototype.addData = function(data) {
	var self = this;
	var user = data.value.operator;
	var actions = data.value.actions;
	var boardId = data.value.boardId;

	if (!self.userData[boardId]) {
		self.initBoard(boardId);
	}
	if (!self.userData[boardId][user]) {
		self.userData[boardId][user] = [];
	}
	var length = self.userData[boardId][user].length;
	actions.forEach(function(action) {
		action.color && (action.color = self.dealColor(action.color));
		if (action.action == 1) {
			// 开始画线
			var line = new Line(user, action);
			// 得按顺序放 稍后处理
			line.show = true;
			self.userData[boardId][user].push(line);
			self.data[boardId].push(line);
			length++;
		} else if (action.action == 2 || action.action == 3) {
			if (length == 0)
				return; //乱序暂时不处理
			var line = self.userData[boardId][user][length - 1];
			line.lines.push({x: action.x, y: action.y, seq: action.seq});
			line.setBorder(action.x, action.y);
			if (action.action == 3) {
				line.endSeq = action.seq;
			}
		} else if (action.action == 6) { // 激光笔先放一放
		} else if (action.action == 7) { // 激光笔先放一放
		} else if (action.action == 8) { // 要修改线的状态
			if (!action.lines)
				return;
			action.lines.forEach(function(line) {
				for (var i = 0; i < self.userData[boardId][line.uid].length; i++) {
					var item = self.userData[boardId][line.uid][i];
					if (item.type == 'line' && item.startSeq == line.seq) {
						item.show = action.display
							? true
							: false;
					} else if (item.type == 'graph' && item.startPoint.seq == line.seq) {
						item.show = action.display
							? true
							: false;
					}
				}
			})
		} else if (action.action == 9) {
			if (!action.moves)
				return;
			action.moves.forEach(function(move) {
				move.x = move.x;
				move.y = move.y;
				for (var i = 0; i < self.userData[self.currentBoard][move.uid].length; i++) {
					var item = self.userData[self.currentBoard][move.uid][i];
					if (item.type == 'line' && item.startSeq == move.seq) {
						// 移动这条线
						var movex = move.x - item.lines[0].x;
						var movey = move.y - item.lines[0].y;
						item.border.maxX += movex;
						item.border.minX += movex;
						item.border.maxY += movey;
						item.border.minY += movey;
						item.lines.forEach(function(line) {
							line.x += movex;
							line.y += movey;
						})
					} else if (item.type == 'graph' && item.startPoint.seq == move.seq) {
						// 移动graph
						var movex = move.x - item.startPoint.x;
						var movey = move.y - item.startPoint.y;
						item.startPoint.x += movex;
						item.startPoint.y += movey;
						item.endPoint.x += movex;
						item.endPoint.y += movey;
					}
				}
			})
		} else if (action.action == 10 || action.action == 11 || action.action == 12) {
			// 这里不区分圆形和椭圆
			var list = {
				10: 'line',
				11: 'oval',
				12: 'rect'
			}
			action.graph = list[action.action];
			action.beginPoint.x = action.beginPoint.x;
			action.endPoint.x = action.endPoint.x;
			action.beginPoint.y = action.beginPoint.y;
			action.endPoint.y = action.endPoint.y;
			action.solid = action.fillRect
				? true
				: false;
			action.show = true;
			var graph = new Graph(user, action);
			self.userData[self.currentBoard][user].push(graph);
			self.data[self.currentBoard].push(graph);
			length++;
		} else if (action.action == 101) {
			// 清空
			self.clear();
		} else if (action.action == 201) {
			// 更换背景图
			self.addBackgroundPic(boardId, action.url);
		} else if (action.action == 202) {
			// 撤销背景图
			self.deleteBackgroundPic(boardId);
		} else if (action.action == 401) {
			var toBoardId = action.toBoardId;
			action.deleteBoards.forEach(function(deleteBoardId) {
				self.removeBoard(deleteBoardId);
			})
			if (!self.data[toBoardId]) {
				self.initBoard(toBoardId);
			}
			self.currentBoard = toBoardId;
			self.infoSwitchBoard({current: toBoardId, list: self.boardList});
		}
	});
	self.needDraw = true;
}

Sketch.prototype.initBoard = function(boardId) {
	this.userData[boardId] = {};
	this.userData[boardId][this.user] = [];
	this.data[boardId] = [];
	this.opData[boardId] = [];
	this.opIndex[boardId] = 0;
	this.backgroundPic[boardId] = {
		url: '',
		user: this.user,
		show: true
	}
	this.boardList.push(boardId);
}

Sketch.prototype.removeBoard = function(boardId) {
	if (this.currentBoard == boardId) {
		console.log('不能删除当前正在使用的白板');
		return false;
	}
	delete this.userData[boardId];
	delete this.data[boardId];
	delete this.opData[boardId];
	delete this.opIndex[boardId];
	if (this.boardList.indexOf(boardId) > -1) {
		this.boardList.splice(this.boardList.indexOf(boardId), 1);
	}
	return true;
}

Sketch.prototype.deleteBoard = function(boardId) {
	var res = this.removeBoard(boardId);
	if (res) {
		this.sendData.push({
			"action": 401,
			"time": parseInt(+ new Date() / 1000),
			"seq": this.getSeq(),
			"toBoardId": this.currentBoard,
			"deleteBoards": [boardId]
		});

		this.option.reportMsg([
			{
				type: 'deleteBoards',
				seq: this.getSeq(),
				content: {
					deleteBoards: [boardId],
					toBoardId: this.currentBoard,
					updateTime: parseInt(+ new Date() / 1000)
				}
			}
		]);
	}
}

Sketch.prototype.getBoardList = function() {
	return this.boardList;
}

Sketch.prototype.getCurrentBoard = function() {
	return this.currentBoard;
}

Sketch.prototype.switchBoard = function(boardId) {
	if (!this.data[boardId]) {
		this.initBoard(boardId);
	}
	this.currentBoard = boardId;

	this.sendData.push({
		"action": 401,
		"time": parseInt(+ new Date() / 1000),
		"seq": this.getSeq(),
		"toBoardId": boardId,
		"deleteBoards": []
	});

	this.option.reportMsg([
		{
			type: 'switchBoard',
			seq: this.getSeq(),
			content: {
				boardId: boardId,
				updateTime: parseInt(+ new Date() / 1000)
			}
		}
	]);

	this.infoSwitchBoard({current: boardId, list: this.boardList});
	this.needDraw = true;
}

Sketch.prototype.getTotalData = function() {
	return shallowClone(this.data);//Object.assign({}, this.data);
}

// 初始化
Sketch.prototype.init = function() {
	var self = this;
	Sketch.prototype.renderCanvas = renderCanvas;
	renderCanvas();

	self.drawInterval = setInterval(function() {
		if (self.needDraw) {
			self.draw();
			self.needDraw = false;
		}
	}, 50);

	self.sendInterval = setInterval(function() {
		if (self.sendData.length > 0) {
			self.sendRequest();
		}
	}, 200);

	// 是否是按下鼠标状态
	var onoff = false;
	// 开始位置
	var startx = -10;
	var starty = -10;
	// 当前位置
	var oldx = -10;
	var oldy = -10;

	var ctx = self.el.getContext("2d");

	function renderCanvas() {
		// self.container.style.position = 'relative';
		self.container.innerHTML = '<canvas width="' + self.width + '" height="' + self.height + '"  style="z-index:10;position:absolute; top:0; left:0;"></canvas>\
																<img width="' + self.width + '" height="' + self.height + '" style="display:none; position:absolute; top:0; left:0;z-index:5;" />';
		self.el = self.container.getElementsByTagName('canvas')[0];
		self.img = self.container.getElementsByTagName('img')[0];

		self.draw();

		self.el.addEventListener("mousemove", draw, true);
		self.el.addEventListener("mousedown", down, false);
		self.el.addEventListener("mouseup", up, false);
		self.el.addEventListener("mouseleave", over, false);

		if(self.option.event){
			for(var i = 0; i < self.option.event.length; i ++){
				var item = self.option.event[i];
				console.log(item);
				self.el.addEventListener(item.type, item.fn, false);
			}
		}

	}

	function down(event) {
		if (!self.canDraw)
			return;
		onoff = true;
		// 每次操作会影响 opData  从第一步起截止到目前的操作步数
		self.opData[self.currentBoard] = self.opData[self.currentBoard].slice(0, self.opIndex[self.currentBoard]);
		oldx = startx = self.getEventLocation(event).x;
		oldy = starty = self.getEventLocation(event).y;
		// 类型是随便画
		if (self.type == 'line') {
			self.cancelSelect();
			var seq = self.getSeq();
			var line = new Line(self.user, {
				time: '3',
				color: self.color,
				thin: self.thin,
				x: oldx,
				y: oldy,
				show: true,
				seq: self.getSeq()
			});
			self.seq = line.seq;
			self.userData[self.currentBoard][self.user].push(line);
			self.data[self.currentBoard].push(line);
			self.opData[self.currentBoard].push(new Operation(self.user, {
				seq: line.seq,
				type: self.type
			}));
			self.opIndex[self.currentBoard]++;
			self.sendData.push({
				"action": 1, // begin画线
				"color": self.formatColor(self.color),
				"scale": 100,
				"thin": self.thin,
				"time": parseInt(+ new Date() / 1000),
				"seq": line.seq,
				"x": oldx,
				"y": oldy
			});
		} else if (self.type == 'eraser') {
			// 橡皮擦
			// 需要遍历全部的data 碰撞检测
			self.cancelSelect();
			var data = eraser(oldx, oldy, self.radius);
			if (data.length > 0) {
				// 放入操作
				self.opData[self.currentBoard].push(new Operation('', {
					seq: data,
					type: self.type
				}));
				self.opIndex[self.currentBoard]++;
				data.length && self.sendData.push({
					"action": 8, // 擦除
					"display": 0,
					"time": parseInt(+ new Date() / 1000),
					"seq": self.getSeq(),
					"x": 0,
					"y": 0,
					lines: data
				});
				data.length && self.option.reportMsg([
					{
						type: 'displayLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							updateTime: parseInt(+ new Date() / 1000),
							display: 0,
							lines: data
						}
					}
				]);
				self.needDraw = true;
			}
		} else if (self.type == 'raser') {
			// 激光笔
			// 激光笔不算入操作
			self.cancelSelect();
			var raser = new Raser(self.user, {
				time: '3',
				color: self.color,
				radius: self.thin,
				x: oldx,
				y: oldy,
				seq: self.getSeq()
			});
			self.seq = raser.seq;
			self.userData[self.currentBoard][self.user].push(raser);
			self.data[self.currentBoard].push(raser);
			self.sendData.push({
				"action": 6, // 激光笔
				"color": self.formatColor(self.color),
				"r": self.thin,
				"seq": raser.seq,
				"x": oldx,
				"y": oldy
			});
			self.needDraw = true;
		} else if (self.type == 'select') {
			// 框选
			// 不算入操作
			self.cancelSelect();
			var select = new Select(self.user, {
				startx: startx,
				starty: starty,
				x: startx,
				y: starty
			});
			self.seq = select.seq;
			self.userData[self.currentBoard][self.user].push(select);
			self.data[self.currentBoard].push(select);
		} else if (self.type == 'pointselect') {
			// 点选不需要额外的操作
			// 不算入操作
			self.cancelSelect();
		} else if (self.type == 'move') {
			// 移动
			// 移动得判断当前点击的位置 是否在选择区域内
			// 算入操作
			if (self.selectedList.length == 0)
				return;
			var status = false;
			for (var i = 0; i < self.selectedList.length; i++) {
				var item = self.selectedList[i];
				if (item.type == 'line') {
					if (item.border.minX <= startx && item.border.maxX >= startx && item.border.minY <= starty && item.border.maxY >= starty) {
						status = true;
						break;
					}
				} else if (item.type == 'graph') {
					if (item.startPoint.x <= startx && item.endPoint.x >= startx && item.startPoint.y <= starty && item.endPoint.y >= starty) {
						status = true;
						break;
					}
				}
			}
			if (!status) {
				self.cancelSelect();
				self.needDraw = true;
				return;
			}
			self.isMoving = true;
			// 这里得先记录下起始坐标
			var origin = [];
			self.selectedList.forEach(function(item) {
				if (item.type == 'line') {
					origin.push({uid: item.user, seq: item.seq, x: item.lines[0].x, y: item.lines[0].y})
				} else if (item.type == 'graph') {
					origin.push({uid: item.user, seq: item.startPoint.seq, x: item.startPoint.x, y: item.startPoint.y})
				}
			})
			self.opData[self.currentBoard].push(new Operation('', {
				seq: {
					origin: origin,
					final: []
				},
				type: self.type
			}));
		} else if (self.type.indexOf('graph') > -1) {
			// 画图形
			// 算入操作
			self.cancelSelect();
			var type = self.type.split('-')[1];
			var graph = new Graph(self.user, {
				time: '3',
				graph: type,
				color: self.color,
				thin: self.thin,
				seq: self.getSeq(),
				beginPoint: {
					x: oldx,
					y: oldy,
					seq: self.getSeq()
				},
				endPoint: {
					x: oldx,
					y: oldy,
					seq: self.getSeq()
				},
				show: true,
				solid: self.type.indexOf('solid') > -1 // 是否实心
			});
			self.seq = graph.seq;
			self.userData[self.currentBoard][self.user].push(graph);
			self.data[self.currentBoard].push(graph);
			self.opData[self.currentBoard].push(new Operation(self.user, {
				seq: graph.startPoint.seq,
				type: 'graph'
			}));
			self.opIndex[self.currentBoard]++;
		}
	}
	function up(event) {
		if (!self.canDraw)
			return;
		onoff = false;
		var newx = self.getEventLocation(event).x;
		var newy = self.getEventLocation(event).y;

		// 类型是随便画
		if (self.type == 'line') {
			var length = self.userData[self.currentBoard][self.user].length;
			var line = self.userData[self.currentBoard][self.user][length - 1];
			line.setBorder(newx, newy);
			var seq = self.getSeq();
			line.lines.push({x: newx, y: newy, seq: seq});
			self.sendData.push({"action": 3, seq: seq, "x": oldx, "y": oldy});
			// 画完线 得report
			var pointList = [];
			line.lines.forEach(function(item) {
				pointList.push({seq: item.seq, x: item.x, y: item.y})
			})
			self.option.reportMsg([
				{
					type: 'addLine',
					seq: self.getSeq(),
					content: {
						boardId: self.currentBoard,
						uid: self.user,
						colorRGBA: self.formatColor(self.color),
						scale: 100,
						width: self.thin,
						time: line.time,
						updateTime: parseInt(+ new Date() / 1000),
						seq: line.seq,
						hidden: 0,
						points: pointList
					}
				}
			]);
		} else if (self.type == 'eraser') {
			// 橡皮擦只支持点击  所以up直接返回就好了
			return;
		} else if (self.type == 'raser') {
			// 激光笔需要修改状态
			var length = self.userData[self.currentBoard][self.user].length;
			var raser = self.userData[self.currentBoard][self.user][length - 1];
			raser.point = {
				x: newx,
				y: newy
			};
			raser.status = 0;
			self.sendData.push({
				"action": 7, // 激光笔
				"seq": raser.seq
			});
			self.needDraw = true;
		} else if (self.type == 'pointselect') {
			// 点选
			// 判断选中了谁  倒着判断
			var status = false; // 是否选中了一块
			for (var i = self.data[self.currentBoard].length - 1; i >= 0; i--) {
				var item = self.data[self.currentBoard][i];
				if (item.type == 'line' && item.show) {
					if (startx < item.border.maxX && startx > item.border.minX && starty < item.border.maxY && starty > item.border.minY) {
						status = true;
						item.select = true;
						self.selectedList = [item];
						self.selectArea = {
							x: item.border.minX,
							y: item.border.minY,
							width: item.border.maxX - item.border.minX,
							height: item.border.maxY - item.border.minY
						};
						break;
					}
				} else if (item.type == 'graph' && item.show) {
					// 区分一下大小的X Y
					var graphLargeX = item.endPoint.x;
					var graphLargeY = item.endPoint.y;
					var graphSmallX = item.startPoint.x;
					var graphSmallY = item.startPoint.y;
					if (startx > graphSmallX && startx < graphLargeX && starty > graphSmallY && starty < graphLargeY) {
						status = true;
						item.select = true;
						self.selectedList = [item];
						self.selectArea = {
							x: graphSmallX,
							y: graphSmallY,
							width: graphLargeX - graphSmallX,
							height: graphLargeY - graphSmallY
						};
						break;
					}
				}
			}
			if (status) {
				self.needDraw = true;
				self.setType('move');
			}
		} else if (self.type == 'select') {
			// 框选
			// 判断选中的区域
			// 由于不清楚 选框中 x y 大小 需要判断下
			var areaLargeX = startx > newx
				? startx
				: newx;
			var areaLargeY = starty > newy
				? starty
				: newy;
			var areasmallX = startx + newx - areaLargeX;
			var areasmallY = starty + newy - areaLargeY;
			for (var i = self.data[self.currentBoard].length - 1; i >= 0; i--) {
				var item = self.data[self.currentBoard][i];
				if (item.type == 'line' && item.show) {
					if (areaLargeX >= item.border.maxX && areaLargeY >= item.border.maxY && areasmallX <= item.border.minX && areasmallY <= item.border.minY) {
						item.select = true;
						self.selectedList.push(item);
					}
				} else if (item.type == 'graph' && item.show) {
					if (areaLargeX >= item.endPoint.x && areaLargeY >= item.endPoint.y && areasmallX <= item.startPoint.x && areasmallY <= item.startPoint.y) {
						item.select = true;
						self.selectedList.push(item);
					}
				}
			}
			self.selectArea = {
				x: areasmallX,
				y: areasmallY,
				width: areaLargeX - areasmallX,
				height: areaLargeY - areasmallY
			};
			// 隐藏总的框选
			var select = self.userData[self.currentBoard][self.user][self.userData[self.currentBoard][self.user].length - 1];
			select.show = false;
			self.needDraw = true;
			self.setType('move');
		} else if (self.type == 'move') {
			self.isMoving = false;
			self.needDraw = true;
			var moves = [];
			if (self.selectedList.length == 0)
				return;
			self.selectedList.forEach(function(item) {
				if (item.type == 'line') {
					moves.push({seq: item.seq, x: item.lines[0].x, y: item.lines[0].y, uid: item.user});
				} else if (item.type == 'graph') {
					moves.push({seq: item.startPoint.seq, x: item.startPoint.x, y: item.startPoint.y, uid: item.user});
				}
			});
			self.sendData.push({
				"action": 9,
				"seq": self.getSeq(),
				"moves": moves,
				"time": parseInt(+ new Date() / 1000)
			});
			// 修改操作
			var final = [];
			self.selectedList.forEach(function(item) {
				if (item.type == 'line') {
					final.push({uid: item.user, seq: item.seq, x: item.lines[0].x, y: item.lines[0].y})
				} else if (item.type == 'graph') {
					final.push({uid: item.user, seq: item.startPoint.seq, x: item.startPoint.x, y: item.startPoint.y})
				}
			});
			var op = self.opData[self.currentBoard][self.opData[self.currentBoard].length - 1];
			op.seq.final = final;
			self.opIndex[self.currentBoard]++;
			// 上报数据
			var reportData = [];
			moves.forEach(function(move) {
				var user = move.uid;
				for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
					var item = self.userData[self.currentBoard][user][i];
					if (item.type == 'line' && move.seq == item.seq) {
						// 添加点的信息
						var pointList = [];
						item.lines.forEach(function(line) {
							pointList.push({seq: line.seq, x: line.x, y: line.y})
						})
						reportData.push({
							type: 'addLine',
							seq: self.getSeq(),
							content: {
								boardId: self.currentBoard,
								uid: item.user,
								colorRGBA: self.formatColor(item.color),
								scale: 100,
								width: item.thin,
								time: item.time,
								updateTime: parseInt(+ new Date() / 1000),
								seq: item.seq,
								hidden: 0,
								points: pointList
							}
						})
					} else if (item.type == 'graph' && move.seq == item.startPoint.seq) {
						var reportMap = {
							'line': 'addPatternLine',
							'oval': 'addPatternCircle',
							'circle': 'addPatternCircle',
							'rect': 'addPatternRectangle'
						};
						var reportMsg = {
							type: reportMap[item.graph],
							seq: self.getSeq(),
							content: {
								boardId: self.currentBoard,
								uid: self.user,
								colorRGBA: self.formatColor(item.color),
								scale: 100,
								width: item.thin,
								time: item.time,
								updateTime: parseInt(+ new Date() / 1000),
								hidden: 0,
								beginPoint: {
									x: item.startPoint.x,
									y: item.startPoint.y,
									seq: item.startPoint.seq
								},
								endPoint: {
									x: item.endPoint.x,
									y: item.endPoint.y,
									seq: item.endPoint.seq
								}
							}
						};

						if (item.graph == 'oval' || item.graph == 'circle') {
							reportMsg.content.fillRect = 0;
						} else if (item.graph == 'rect') {
							reportMsg.content.fillRect = 0;
							reportMsg.content.cornerRadius = 0;
						}
						reportData.push(reportMsg);
					}
				}
			});
			self.option.reportMsg(reportData);
		} else if (self.type.indexOf('graph') > -1) {
			var length = self.userData[self.currentBoard][self.user].length;
			var graph = self.userData[self.currentBoard][self.user][length - 1];
			graph.endPoint.x = newx;
			graph.endPoint.y = newy;
			if (graph.graph == 'circle')
				circleFix(graph);

			self.needDraw = true;
			var sendData = {
				seq: graph.seq,
				time: parseInt(+ new Date() / 1000),
				color: self.formatColor(self.color),
				scale: 100,
				thin: self.thin,
				beginPoint: {
					x: graph.startPoint.x,
					y: graph.startPoint.y,
					seq: graph.startPoint.seq
				},
				endPoint: {
					x: graph.endPoint.x,
					y: graph.endPoint.y,
					seq: graph.endPoint.seq
				}
			};
			var sendMap = {
				'line': 10,
				'oval': 11,
				'circle': 11,
				'rect': 12
			};
			sendData.action = sendMap[graph.graph];

			var reportMap = {
				'line': 'addPatternLine',
				'oval': 'addPatternCircle',
				'circle': 'addPatternCircle',
				'rect': 'addPatternRectangle'
			};
			var reportMsg = {
				type: reportMap[graph.graph],
				seq: self.getSeq(),
				content: {
					boardId: self.currentBoard,
					uid: self.user,
					colorRGBA: self.formatColor(self.color),
					scale: 100,
					width: self.thin,
					time: graph.time,
					updateTime: parseInt(+ new Date() / 1000),
					hidden: 0,
					beginPoint: {
						x: graph.startPoint.x,
						y: graph.startPoint.y,
						seq: graph.startPoint.seq
					},
					endPoint: {
						x: graph.endPoint.x,
						y: graph.endPoint.y,
						seq: graph.endPoint.seq
					}
				}
			};

      if (sendData.action > 10) {
        sendData.fillRect = graph.solid ? 1 : 0;
        reportMsg.content.fillRect = graph.solid ? 1 : 0;
       };
		
			if (sendData.action == 12) {
				sendData.cornerRadius = 0;
				reportMsg.content.cornerRadius = 0;
			}
			self.sendData.push(sendData);
			// 上报数据
			self.option.reportMsg([reportMsg]);
		}
	}
	function draw(event) {
		if (!self.canDraw)
			return;
		if (self.type == 'eraser') {
			// 橡皮擦只支持点击  所以draw直接返回就好了
			return;
		}
		if (onoff) {
			var newx = self.getEventLocation(event).x;
			var newy = self.getEventLocation(event).y;

			// 类型是随便画
			if (self.type == 'line') {
				ctx.beginPath();
				ctx.moveTo(oldx / 10000 * self.width, oldy / 10000 * self.height);
				ctx.lineTo(newx / 10000 * self.width, newy / 10000 * self.height);
				ctx.strokeStyle = self.color;
				ctx.lineWidth = self.thin / 10000 * self.height;
				ctx.lineCap = 'round';
				ctx.stroke();

				var length = self.userData[self.currentBoard][self.user].length;
				var line = self.userData[self.currentBoard][self.user][length - 1];
				line.setBorder(newx, newy);
				var seq = self.getSeq()
				line.lines.push({x: newx, y: newy, seq: seq});

				self.sendData.push({"action": 2, seq: seq, "x": oldx, "y": oldy});
			} else if (self.type == 'raser') {
				// 激光笔需要修改状态
				var length = self.userData[self.currentBoard][self.user].length;
				var raser = self.userData[self.currentBoard][self.user][length - 1];
				raser.location = {
					x: newx,
					y: newy
				};
				self.needDraw = true;
				self.sendData.push({
					"action": 6,
					"seq": self.getSeq(),
					"x": oldx,
					"y": oldy,
					"color": self.formatColor(self.color),
					"r": self.thin
				});
			} else if (self.type == 'select') { // 框选
				var length = self.userData[self.currentBoard][self.user].length;
				var select = self.userData[self.currentBoard][self.user][length - 1];
				select.location = {
					x: newx,
					y: newy
				};
				self.needDraw = true;
			} else if (self.type == 'pointselect') { //点选
				// 点选不需要操作
			} else if (self.type == 'move') { // 移动区域
				if (self.selectedList.length > 0) {
					for (var i = 0; i < self.selectedList.length; i++) {
						var item = self.selectedList[i];
						var movex = newx - oldx;
						var movey = newy - oldy;
						if (item.type == 'line') {
							item.border.maxX += movex;
							item.border.minX += movex;
							item.border.maxY += movey;
							item.border.minY += movey;
							item.lines.forEach(function(line) {
								line.x += movex;
								line.y += movey;
							})
						} else if (item.type == 'graph') {
							item.startPoint.x += movex;
							item.startPoint.y += movey;
							item.endPoint.x += movex;
							item.endPoint.y += movey;
						}
					}
					self.selectArea.x += movex;
					self.selectArea.y += movey;
					self.needDraw = true;
				}
			} else if (self.type.indexOf('graph') > -1) {
				var length = self.userData[self.currentBoard][self.user].length;
				var graph = self.userData[self.currentBoard][self.user][length - 1];
				graph.endPoint.x = newx;
				graph.endPoint.y = newy;
				if (graph.graph == 'circle')
					circleFix(graph);
				self.needDraw = true;
			}
			// 更新数据
			oldx = newx;
			oldy = newy;
		}
	}
	function over(event) {
		if (!self.canDraw)
			return;

		// 鼠标离开
		if (onoff == true) { // 正在画，要结束当前画画内容
			var length = self.userData[self.currentBoard][self.user].length;
			var paint = self.userData[self.currentBoard][self.user][length - 1];
			if (paint.type == 'line') {
				// 要取离开前的最后一个点
				self.sendData.push({
					"action": 3,
					"x": paint.lines[paint.lines.length - 1].x,
					"y": paint.lines[paint.lines.length - 1].y
				});
			} else if (paint.type == 'raser') {
				paint.status = 0;
				self.needDraw = true;
			}

			onoff = false;
		}
	}

	function eraser(x, y, radius) {
		// 遍历data
		var sendData = [];
		self.data[self.currentBoard].forEach(function(item) {
			if (item.type == 'line' && item.show) {
				// 随便的画线
				var isRelative = false; // 是否碰撞
				// 先检测是否在矩形区域内
				var maxX = item.border.maxX;
				var maxY = item.border.maxY;
				var minX = item.border.minX;
				var minY = item.border.minY;
				if (maxX >= x && maxY >= y && minX <= x && minY <= y) {
					isRelative = true;
				} else if (maxX >= x && minX <= x) {
					var distance = Math.min(Math.abs(maxY - y), Math.abs(minY - y));
					if (distance <= radius)
						isRelative = true;
					}
				else if (maxY >= y && minY <= y) {
					var distance = Math.min(Math.abs(maxX - x), Math.abs(minX - x));
					if (distance <= radius)
						isRelative = true;
					}
				else if (maxX < x) {
					var distance;
					if (maxY < y) {
						distance = Math.pow(x - maxX, 2) + Math.pow(y - maxY, 2);
					} else {
						distance = Math.pow(x - maxX, 2) + Math.pow(y - minY, 2);
					}
					if (distance <= Math.pow(radius, 2))
						isRelative = true;
					}
				else {
					var distance;
					if (maxY < y) {
						distance = Math.pow(x - minX, 2) + Math.pow(y - maxY, 2);
					} else {
						distance = Math.pow(x - minX, 2) + Math.pow(y - minY, 2);
					}
					if (distance <= Math.pow(radius, 2))
						isRelative = true;
					}
				if (!isRelative) {
					// 没和矩形碰撞 肯定不会和曲线碰撞 退出
					return;
				}
				isRelative = false;
				// 挨个计算碰撞
				for (var i = 1; i < item.lines.length; i++) {
					var line = item.lines[i];
					var old = item.lines[i - 1];
					var distance = getDistance(x, y, line.x, line.y, old.x, old.y);
					if (distance <= (radius + self.thin) * (radius + self.thin)) {
						isRelative = true;
						break;
					}
				}

				if (isRelative) {
					item.show = false;
					sendData.push({uid: item.user, seq: item.seq});
				}
			} else if (item.type == 'graph' && item.show) {
				if (item.graph == 'line') { // 擦除直线
					var distance = getDistance(x, y, item.startPoint.x, item.startPoint.y, item.endPoint.x, item.endPoint.y);
					if (distance <= (radius + self.thin) * (radius + self.thin)) {
						item.show = false;
						sendData.push({uid: item.user, seq: item.startPoint.seq})
					}
				} else if (item.graph == 'rect') { // 擦掉矩形
					if (item.solid) { // 实心  只需判断是否在内部
						if (x > item.startPoint.x && y > item.startPoint.y && x < item.endPoint.x && y < item.endPoint.y) {
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq})
						}
					} else { // 点击的位置在四条边附近  简化为 点到四条线段的距离
						var distance1 = getDistance(x, y, item.startPoint.x, item.startPoint.y, item.startPoint.x, item.endPoint.y);
						var distance2 = getDistance(x, y, item.startPoint.x, item.startPoint.y, item.endPoint.x, item.startPoint.y);
						var distance3 = getDistance(x, y, item.endPoint.x, item.endPoint.y, item.startPoint.x, item.endPoint.y);
						var distance4 = getDistance(x, y, item.endPoint.x, item.endPoint.y, item.endPoint.x, item.startPoint.y);
						if (Math.min(distance1, distance2, distance3, distance4) <= (radius + self.thin) * (radius + self.thin)) {
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq});
						}
					}
				} else if (item.graph == 'circle') {
					var centerX = (item.startPoint.x + item.endPoint.x) / 2;
					var centerY = (item.startPoint.y + item.endPoint.y) / 2;
					var circleRadius = Math.sqrt(Math.pow(item.startPoint.x - item.endPoint.x, 2) + Math.pow(item.startPoint.y - item.endPoint.y, 2)) / 2;
					var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
					if (item.solid) { // 实心  只需判断是否在内部
						if (distance < (circleRadius + radius)) {
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq})
						}
					} else { // 空心 判断距离圆心的距离
						if (Math.abs(circleRadius - distance) <= (radius + self.thin)) {
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq})
						}
					}
				} else if (item.graph == 'oval') {
					//
					var centerX = (item.startPoint.x + item.endPoint.x) / 2;
					var centerY = (item.startPoint.y + item.endPoint.y) / 2;
					var a = Math.abs(item.startPoint.x - item.endPoint.x) / 2;
					var b = Math.abs(item.startPoint.y - item.endPoint.y) / 2;
					// 计算圆心距离
					var distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
					if (distance == 0) { // 刚好重合的话
						if (item.solid) { // 实心  直接擦除
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq});
						} else if (a <= (radius + self.thin) || b <= (radius + self.thin)) { // 空心 比较长短轴与 橡皮擦范围的大小
							item.show = false;
							sendData.push({uid: item.user, seq: item.startPoint.seq});
						}
					} else {
						// 计算tan
						var tan = (y - centerY) / (x - centerX);
						var difX = Math.sqrt(1 / (1 / (a * a) + Math.pow(tan / b, 2)));
						var difY = Math.sqrt(1 / (Math.pow(tan / a, 2) + 1 / (b * b)));

						var nodeX = x > centerX
							? (centerX + difX)
							: (centerX - difX);
						var nodeY = y > centerY
							? (centerY + difY)
							: (centerY - difY);
						if (item.solid) {
							// 实心 检测横坐标之差
							var centerDifX = Math.abs(x - centerX);
							if (difX + radius > centerDifX) {
								item.show = false;
								sendData.push({uid: item.user, seq: item.startPoint.seq})
							}
						} else {
							// 空心 交点是否在橡皮擦圆内
							distance = Math.pow(x - nodeX, 2) + Math.pow(y - nodeY, 2);
							if (distance <= (radius + self.thin) * (radius + self.thin)) {
								item.show = false;
								sendData.push({uid: item.user, seq: item.startPoint.seq})
							}
						}
					}
				}
			}
		})

		return sendData;
	}

	// 点到线段的距离
	function getDistance(x, y, x1, y1, x2, y2) {
		// 1. 先求交点坐标
		var point = {};
		if (x1 == x2) {
			point.x = x1;
			point.y = y;
		} else {
			var A = (y1 - y2) / (x1 - x2);
			var B = y1 - A * x1;
			var m = x + A * y;
			point.x = (m - A * B) / (A * A + 1);
			point.y = A * point.x + B;
		}

		// 判断是否在线段内
		if (point.x >= x1 && point.x <= x2 || point.x <= x1 && point.x >= x2) {
			// 求点的距离
			return (point.x - x) * (point.x - x) + (point.y - y) * (point.y - y);
		} else {
			// 点到线段两个断点的最小值
			return Math.min((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y), (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
		}
	}

	// 圆的话  需要修正endPoint
	function circleFix(circle) {
		// 计算占比
		var width = Math.abs(circle.startPoint.x - circle.endPoint.x) * self.width / 10000;
		var height = Math.abs(circle.startPoint.y - circle.endPoint.y) * self.height / 10000;
		if (width > height) { // 比较宽的矩形  需要终点修改 x 值
			circle.endPoint.x = circle.startPoint.x < circle.endPoint.x
				? (circle.startPoint.x + height * 10000 / self.width)
				: (circle.startPoint.x - height * 10000 / self.width);
		} else { // 比较高的矩形 需要终点修改 y 值
			circle.endPoint.y = circle.startPoint.y < circle.endPoint.y
				? circle.startPoint.y + width * 10000 / self.height
				: circle.startPoint.y - width * 10000 / self.height;
		}
	}

	// 将graph的顶点统一改为左上角开始和右下角结束
	function graphFix(graph) {
		graph.startPoint = {
			x: graph.startPoint.x > graph.endPoint.x
				? graph.endPoint.x
				: graph.startPoint.x,
			y: graph.startPoint.y > graph.endPoint.y
				? graph.endPoint.y
				: graph.startPoint.y,
			seq: graph.startPoint.seq
		};
		graph.endPoint = {
			x: graph.startPoint.x > graph.endPoint.x
				? graph.startPoint.x
				: graph.endPoint.x,
			y: graph.startPoint.y > graph.endPoint.y
				? graph.startPoint.y
				: graph.endPoint.y,
			seq: graph.endPoint.seq
		};
	}
}

// 发送修改数据
Sketch.prototype.sendRequest = function() {
	var self = this;
	// 发请求
	var sendData = {
		seq: 1,
		timestamp: parseInt(+ new Date() / 1000),
		value: {
			boardId: self.currentBoard,
			operator: self.user,
			actions: self.sendData
		}
	}
	self.sendMsg(sendData);
	// 发送内容归0
	self.sendData = [];
}

// 修改颜色
Sketch.prototype.setColor = function(color) {
	this.cancelSelect();
	this.color = this.dealColor(color);
}

// 修改画笔粗细
Sketch.prototype.setThin = function(thin) {
	this.cancelSelect();
	this.thin = thin;
}

// 修改橡皮擦粗细
Sketch.prototype.setRadius = function(radius) {
	this.cancelSelect();
	this.radius = radius;
}

// 修改画画类型
// 这个时候需要取消被选择的框
Sketch.prototype.setType = function(type) {
	if (type != 'move') {
		this.cancelSelect();
	}
	this.type = type;
}

// revert操作
Sketch.prototype.revert = function() {
	this.cancelSelect();
	var self = this;
	var operation = this.opData[self.currentBoard][this.opIndex[self.currentBoard] - 1];
	if (operation.type == 'line') { // 说明是画了一个线  这里要隐藏
		for (var i = 0; i < this.userData[self.currentBoard][operation.user].length; i++) {
			var item = this.userData[self.currentBoard][operation.user][i];
			if (operation.seq == item.seq) {
				item.show = false;
				// 这里需要sendData
				this.sendData.push({
					"action": 8, // 擦除
					"display": 0,
					"time": parseInt(+ new Date() / 1000),
					"seq": self.getSeq(),
					"lines": [
						{
							uid: operation.user,
							seq: operation.seq
						}
					]
				});
				// 上报
				self.option.reportMsg([
					{
						type: 'displayLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							updateTime: parseInt(+ new Date() / 1000),
							display: 0,
							lines: [
								{
									uid: operation.user,
									seq: operation.seq
								}
							]
						}
					}
				]);
				break;
			}
		}
	} else if (operation.type == 'eraser') { // 说明擦了东西 显示出来就好了
		operation.seq.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					item.show = true;
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					item.show = true;
				}
			}
		});
		this.sendData.push({
			"action": 8, // 擦除
			"display": 1,
			"time": parseInt(+ new Date() / 1000),
			"seq": self.getSeq(),
			"lines": operation.seq
		});
		// 上报
		self.option.reportMsg([
			{
				type: 'displayLine',
				seq: self.getSeq(),
				content: {
					boardId: self.currentBoard,
					updateTime: parseInt(+ new Date() / 1000),
					display: 1,
					lines: operation.seq
				}
			}
		]);
	} else if (operation.type == 'graph') {
		for (var i = 0; i < this.userData[self.currentBoard][operation.user].length; i++) {
			var item = this.userData[self.currentBoard][operation.user][i];
			if (item.type == 'graph' && operation.seq == item.startPoint.seq) {
				item.show = false;
				// 这里需要sendData
				this.sendData.push({
					"action": 8, // 擦除
					"display": 0,
					"time": parseInt(+ new Date() / 1000),
					"seq": self.getSeq(),
					"lines": [
						{
							uid: operation.user,
							seq: operation.seq
						}
					]
				});
				// 上报
				self.option.reportMsg([
					{
						type: 'displayLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							updateTime: parseInt(+ new Date() / 1000),
							display: 0,
							lines: [
								{
									uid: operation.user,
									seq: operation.seq
								}
							]
						}
					}
				]);
				break;
			}
		}
	} else if (operation.type == 'move') {
		// 得回到origin的位置
		var moves = [];
		operation.seq.origin.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					var movex = seq.x - item.lines[0].x;
					var movey = seq.y - item.lines[0].y;
					item.border.maxX += movex;
					item.border.minX += movex;
					item.border.maxY += movey;
					item.border.minY += movey;
					item.lines.forEach(function(line) {
						line.x += movex;
						line.y += movey;
					});
					moves.push({uid: user, seq: seq.seq, x: seq.x, y: seq.y});
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					var movex = seq.x - item.startPoint.x;
					var movey = seq.y - item.startPoint.y;
					item.startPoint.x += movex;
					item.startPoint.y += movey;
					item.endPoint.x += movex;
					item.endPoint.y += movey;
					moves.push({uid: user, seq: seq.seq, x: seq.x, y: seq.y});
				}
			}
		})

		this.sendData.push({
			"action": 9, // 擦除
			"time": parseInt(+ new Date() / 1000),
			"seq": self.getSeq(),
			"moves": moves
		});

		// report
		var reportData = [];
		operation.seq.origin.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					// 添加点的信息
					var pointList = [];
					item.lines.forEach(function(line) {
						pointList.push({seq: line.seq, x: line.x, y: line.y})
					})
					reportData.push({
						type: 'addLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							uid: item.user,
							colorRGBA: self.formatColor(item.color),
							scale: 100,
							width: item.thin,
							time: item.time,
							updateTime: parseInt(+ new Date() / 1000),
							seq: item.seq,
							hidden: 0,
							points: pointList
						}
					})
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					var reportMap = {
						'line': 'addPatternLine',
						'oval': 'addPatternCircle',
						'circle': 'addPatternCircle',
						'rect': 'addPatternRectangle'
					};
					var reportMsg = {
						type: reportMap[item.graph],
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							uid: self.user,
							colorRGBA: self.formatColor(item.color),
							scale: 100,
							width: item.thin,
							time: item.time,
							updateTime: parseInt(+ new Date() / 1000),
							hidden: 0,
							beginPoint: {
								x: item.startPoint.x,
								y: item.startPoint.y,
								seq: item.startPoint.seq
							},
							endPoint: {
								x: item.endPoint.x,
								y: item.endPoint.y,
								seq: item.endPoint.seq
							}
						}
					};

					if (item.graph == 'oval' || item.graph == 'circle') {
						reportMsg.content.fillRect = 0;
					} else if (item.graph == 'rect') {
						reportMsg.content.fillRect = 0;
						reportMsg.content.cornerRadius = 0;
					}
					reportData.push(reportMsg);
				}
			}
		});
		self.option.reportMsg(reportData);
	}

	this.opIndex[self.currentBoard]--;
	this.needDraw = true;
}

// 能否回退
Sketch.prototype.canRevert = function() {
	if (this.opIndex[this.currentBoard] == 0) {
		return false;
	}
	return true;
}

// process操作
Sketch.prototype.process = function() {
	this.cancelSelect();
	var self = this;
	var operation = this.opData[self.currentBoard][this.opIndex[self.currentBoard]];
	if (operation.type == 'line') { // 说明是画了一个线  这里要展示
		for (var i = 0; i < this.userData[self.currentBoard][operation.user].length; i++) {
			var item = this.userData[self.currentBoard][operation.user][i];
			if (operation.seq == item.seq) {
				item.show = true;
				// 这里需要sendData
				this.sendData.push({
					"action": 8, // 擦除
					"display": 1,
					"time": parseInt(+ new Date() / 1000),
					"seq": self.getSeq(),
					"lines": [
						{
							uid: operation.user,
							seq: operation.seq
						}
					]
				});
				// 上报
				self.option.reportMsg([
					{
						type: 'displayLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							updateTime: parseInt(+ new Date() / 1000),
							display: 1,
							lines: [
								{
									uid: operation.user,
									seq: operation.seq
								}
							]
						}
					}
				]);
				break;
			}
		}
	} else if (operation.type == 'eraser') { // 说明擦了东西 显示要擦掉
		operation.seq.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					item.show = true;
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					item.show = true;
				}
			}
		});
		this.sendData.push({
			"action": 8, // 擦除
			"display": 0,
			"time": parseInt(+ new Date() / 1000),
			"seq": self.getSeq(),
			"lines": operation.seq
		});
		// 上报
		self.option.reportMsg([
			{
				type: 'displayLine',
				seq: self.getSeq(),
				content: {
					boardId: self.currentBoard,
					updateTime: parseInt(+ new Date() / 1000),
					display: 1,
					lines: operation.seq
				}
			}
		]);
	} else if (operation.type == 'graph') { // 展示
		for (var i = 0; i < this.userData[self.currentBoard][operation.user].length; i++) {
			var item = this.userData[self.currentBoard][operation.user][i];
			if (item.type == 'graph' && operation.seq == item.startPoint.seq) {
				item.show = true;
				// 这里需要sendData
				this.sendData.push({
					"action": 8, // 擦除
					"display": 1,
					"time": parseInt(+ new Date() / 1000),
					"seq": self.getSeq(),
					"lines": [
						{
							uid: operation.user,
							seq: operation.seq
						}
					]
				});
				// 上报
				self.option.reportMsg([
					{
						type: 'displayLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							updateTime: parseInt(+ new Date() / 1000),
							display: 0,
							lines: [
								{
									uid: operation.user,
									seq: operation.seq
								}
							]
						}
					}
				]);
				break;
			}
		}
	} else if (operation.type == 'move') {
		// 得回到final的位置
		var moves = [];
		operation.seq.final.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					var movex = seq.x - item.lines[0].x;
					var movey = seq.y - item.lines[0].y;
					item.border.maxX += movex;
					item.border.minX += movex;
					item.border.maxY += movey;
					item.border.minY += movey;
					item.lines.forEach(function(line) {
						line.x += movex;
						line.y += movey;
					});
					moves.push({uid: user, seq: seq.seq, x: seq.x, y: seq.y});
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					var movex = seq.x - item.startPoint.x;
					var movey = seq.y - item.startPoint.y;
					item.startPoint.x += movex;
					item.startPoint.y += movey;
					item.endPoint.x += movex;
					item.endPoint.y += movey;
					moves.push({uid: user, seq: seq.seq, x: seq.x, y: seq.y});
				}
			}
		})

		this.sendData.push({
			"action": 9, // 擦除
			"time": parseInt(+ new Date() / 1000),
			"seq": self.getSeq(),
			"moves": moves
		});

		var reportData = [];
		operation.seq.final.forEach(function(seq) {
			var user = seq.uid;
			for (var i = 0; i < self.userData[self.currentBoard][user].length; i++) {
				var item = self.userData[self.currentBoard][user][i];
				if (item.type == 'line' && seq.seq == item.seq) {
					// 添加点的信息
					var pointList = [];
					item.lines.forEach(function(line) {
						pointList.push({seq: line.seq, x: line.x, y: line.y})
					})
					reportData.push({
						type: 'addLine',
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							uid: item.user,
							colorRGBA: self.formatColor(item.color),
							scale: 100,
							width: item.thin,
							time: item.time,
							updateTime: parseInt(+ new Date() / 1000),
							seq: item.seq,
							hidden: 0,
							points: pointList
						}
					})
				} else if (item.type == 'graph' && seq.seq == item.startPoint.seq) {
					var reportMap = {
						'line': 'addPatternLine',
						'oval': 'addPatternCircle',
						'circle': 'addPatternCircle',
						'rect': 'addPatternRectangle'
					};
					var reportMsg = {
						type: reportMap[item.graph],
						seq: self.getSeq(),
						content: {
							boardId: self.currentBoard,
							uid: self.user,
							colorRGBA: self.formatColor(item.color),
							scale: 100,
							width: item.thin,
							time: item.time,
							updateTime: parseInt(+ new Date() / 1000),
							hidden: 0,
							beginPoint: {
								x: item.startPoint.x,
								y: item.startPoint.y,
								seq: item.startPoint.seq
							},
							endPoint: {
								x: item.endPoint.x,
								y: item.endPoint.y,
								seq: item.endPoint.seq
							}
						}
					};

					if (item.graph == 'oval' || item.graph == 'circle') {
						reportMsg.content.fillRect = 0;
					} else if (item.graph == 'rect') {
						reportMsg.content.fillRect = 0;
						reportMsg.content.cornerRadius = 0;
					}
					reportData.push(reportMsg);
				}
			}
		});
		self.option.reportMsg(reportData);
	}
	this.opIndex[self.currentBoard]++;
	this.needDraw = true;
}

// 能否回退
Sketch.prototype.canProcess = function() {
	if (this.opIndex[this.currentBoard] == this.opData[this.currentBoard].length) {
		return false;
	}
	return true;
}

// 清屏操作
Sketch.prototype.clear = function() {
	// 变量初始化
	this.data[this.currentBoard] = [];
	this.opData[this.currentBoard] = [];
	this.opIndex[this.currentBoard] = 0;
	this.userData[this.currentBoard] = {};
	this.userData[this.currentBoard][this.user] = [];
	this.backgroundPic[this.currentBoard] = {
		url: '',
		user: ''
	};
	this.color = this.dealColor(this.option.color || 4278190335);
	this.thin = this.option.thin || 100;
	this.radius = this.option.radius || 100;
	this.backgroundColor = this.option.backgroundColor || '#ffffff';
	this.type = 'line';
	this.cancelSelect();
	this.needDraw = true;
}

// 需要对外发送的清空操作
Sketch.prototype.sendClear = function() {
	this.clear();
	this.sendData.push({action: 101, seq: this.getSeq()});
	this.option.reportMsg([
		{
			type: 'clean',
			seq: this.getSeq(),
			content: {
				boardId: self.currentBoard,
				updateTime: parseInt(+ new Date() / 1000)
			}
		}
	]);
}
Sketch.prototype.addBackgroundPic = function(boardId, url) {
	this.cancelSelect();
	this.backgroundPic[boardId].url = url;
	this.backgroundPic[boardId].show = true;
	this.needDraw = true;
}

Sketch.prototype.setBackgroundPic = function(url) {
	this.cancelSelect();
	this.addBackgroundPic(this.currentBoard, url);
	this.sendData.push({
		"action": 201,
		"url": url,
		"time": parseInt(+ new Date() / 1000),
		"seq": this.getSeq(),
		"mode": 0,
		"cleanBoard": 0
	});
	this.option.reportMsg([
		{
			type: 'image',
			seq: this.getSeq(),
			content: {
				boardId: this.currentBoard,
				updateTime: parseInt(+ new Date() / 1000),
				url: url,
				mode: 0
			}
		}
	]);
};

Sketch.prototype.deleteBackgroundPic = function(boardId) {
	this.cancelSelect();
	this.backgroundPic[boardId].show = false;
	this.img.style.display = 'none';
	this.needDraw = true;
}
//  取消背景图
Sketch.prototype.cancelBackgroundPic = function() {
	this.cancelSelect();
	this.deleteBackgroundPic(this.currentBoard);
	this.sendData.push({"action": 202, "seq": this.getSeq()});
	this.option.reportMsg([
		{
			type: 'image',
			seq: this.getSeq(),
			content: {
				boardId: this.currentBoard,
				updateTime: parseInt(+ new Date() / 1000),
				url: '',
				mode: 0
			}
		}
	]);
}

//  清空被选择的区域
Sketch.prototype.cancelSelect = function() {
	for (var i = 0; i < this.selectedList.length; i++) {
		var item = this.selectedList[i];
		item.select = false;
	}
	this.selectedList = [];
	this.selectArea = {
		x: 0,
		y: 0,
		width: 0,
		height: 0
	};
	this.needDraw = true;
}

// 随便画画
function Line(user, option) {
	// 开始画线之后 颜色、粗细等参数是不会变的
	// 开始画线的action 作为传参
	this.user = user; // line属于的user
	this.type = 'line'; // 类型为 画线
	this.seq = option.seq; // seq 唯一编号
	this.show = option.show; // 是否展示
	this.status = 'begin'; // 线的状态  线的状态是没用的
	this.select = false; // 是否被选了
	this.color = option.color;
	this.time = parseInt(+ new Date() / 1000, 10);
	this.thin = option.thin;
	this.startSeq = option.seq;
	this.endSeq = 0;
	// 每一个点  {x, y, seq}
	this.lines = [
		{
			x: option.x,
			y: option.y,
			seq: option.seq
		}
	];
	// 线所在矩形区域的边界
	this.border = {
		maxX: option.x,
		maxY: option.y,
		minX: option.x,
		minY: option.y
	}
}

Line.prototype.setBorder = function(x, y) {
	if (x + this.thin > this.border.maxX) {
		this.border.maxX = x + this.thin;
	}
	if (x - this.thin < this.border.minX) {
		this.border.minX = x - this.thin;
	}
	if (y + this.thin > this.border.maxY) {
		this.border.maxY = y + this.thin;
	}
	if (y - this.thin < this.border.minY) {
		this.border.minY = y - this.thin;
	}
}

// 激光笔
function Raser(user, option) {
	this.user = user;
	this.type = 'raser';
	this.seq = option.seq; // seq 唯一编号
	this.show = true; // 激光笔应该不需要 show  这个属性
	this.status = 1; // 激光笔的状态  正在用 1 以及 结束了 0
	this.color = option.color;
	this.radius = option.radius;
	this.location = {
		x: option.x,
		y: option.y
	};
}

// 选择框
// 默认是点选 pointselect  点选不需要重绘
// 当某一个滑动距离变大时 认为变成了 框选 select  需要重绘
function Select(user, option) {
	this.user = user;
	this.type = 'select';
	this.seq = Math.floor(Math.random() * 100); // seq 唯一编号
	this.show = true; // 是否展示框选
	this.color = option.color;
	this.startInfo = {
		x: option.startx,
		y: option.starty
	}
	this.location = {
		x: option.x,
		y: option.y
	};
}

// 固定图形
function Graph(user, option) {
	this.user = user;
	this.type = 'graph';
	this.graph = option.graph; // line:直线 circle:圆 rect: 矩形
	this.seq = option.seq; // seq 唯一编号
	this.show = option.show; // 是否展示
	this.status = 'begin'; // 图形的状态
	this.select = false; // 是否被选了
	this.time = parseInt(+ new Date() / 1000, 10);
	this.color = option.color;
	this.thin = option.thin;
	this.solid = option.solid || false; // 是否实心
	// 记录开始点与结束点
	this.startPoint = {
		x: option.beginPoint.x,
		y: option.beginPoint.y,
		seq: option.beginPoint.seq
	};
	this.endPoint = {
		x: option.endPoint.x,
		y: option.endPoint.y,
		seq: option.endPoint.seq
	};
}

// 操作的对象  user应该就是本地对象了
function Operation(user, option) {
	this.user = user;
	// 画画类型
	this.type = option.type;
	// 操作的seqs  是个数字或者数组
	this.seq = option.seq;
}


function shallowClone(copyObj) {
	var obj = {};
	for ( var i in copyObj) {
	  obj[i] = copyObj[i];
	}
	return obj;
}

//export default Sketch;
